package com.voe;

import com.voe.callback.Transport;
import com.voe.callback.VoEConnectionObserver;
import com.voe.common.OutputParam;
import com.voe.common.ReturnValue;
import com.voe.common.Utility;

/**This sub-API supports the following functionalities:<br/>
*<br/>
*- External protocol support.<br/>
*- Extended port and address APIs.<br/>
*- Port and address filters.<br/>
*- Windows GQoS functions.<br/>
*- Packet timeout notification.<br/>
*- Dead-or-Alive connection observations.<br/>
*- Transmission of raw RTP/RTCP packets into existing channels.<br/>
*<br/>
*Usage example, omitting error checking:<br/>
*<br/>
*VoiceEngine voe = VoiceEngine.createInterface();<br/>
*VoEBase base = VoEBase.createInterface(voe);<br/>
*VoENetwork netw  = VoENetwork.createInterface(voe);<br/>
*base.init();<br/>
*int ch = base.createChannel();<br/>
*...<br/>
*netw.setPeriodicDeadOrAliveStatus(ch, true);<br/>
*...<br/>
*base.deleteChannel(ch);<br/>
*base.terminate();<br/>
*base.release();<br/>
*netw.release();<br/>
*voe.release();<br/>
*/
public class VoENetwork {

	// [start] apis
	
	public static VoENetwork createInstance(VoiceEngine voiceEngine) {

		long p = GetInterface(voiceEngine._p);
		if(p != 0)
			return new VoENetwork(p);
		return null;
	}

	public void release() {
		if (_p != 0) {
			Release(_p);
		}
	}
	
	/** Installs and enables a user-defined external transport protocol for a<br/>
	 *  specified |channel|.
	 */
	public int registerExternalTransport(int channel, Transport transport) {
		Utility.throwNullPointerException(transport, "transport");
		return RegisterExternalTransport(_p, channel, transport);
	}

	/** Removes and disables a user-defined external transport protocol for a<br/>
	 *  specified |channel|.
	 */
	public int deRegisterExternalTransport(int channel) {
		return DeRegisterExternalTransport(_p, channel);
	}

	/** The packets received from the network should be passed to this<br/>
	 *  function when external transport is enabled. Note that the data<br/>
	 *  including the RTP-header must also be given to the VoiceEngine.
	 */
	public int receivedRTPPacket(int channel, byte[] buffer) {
		return ReceivedRTPPacket(_p, channel, buffer);
	}

	/** The packets received from the network should be passed to this<br/>
	 *  function when external transport is enabled. Note that the data<br/>
	 *  including the RTCP-header must also be given to the VoiceEngine.
	 */
	public int receivedRTCPPacket(int channel, byte[] buffer) {
		return ReceivedRTCPPacket(_p, channel, buffer);
	}

	/** Gets the source ports and IP address of incoming packets on a<br/>
	 *  specific |channel|.
	 */
	public int getSourceInfo(int channel, ReturnValue<Integer> rtpPort, 
			ReturnValue<Integer> rtcpPort, ReturnValue<String> ipAddr) {
		OutputParam output = new OutputParam();
		int result = GetSourceInfo(_p, channel, output);
		if(result == 0) {
			rtpPort.setValue((Integer) output.getObject()[0]);
			rtcpPort.setValue((Integer) output.getObject()[1]);
			ipAddr.setValue((String) output.getObject()[2]);
		}
		return result;
	}

	/** Gets the local (host) IP address.
	 */
	public int getLocalIP(ReturnValue<String> ipAddr, boolean ipv6) {
		OutputParam output = new OutputParam();
		int result = GetLocalIP(_p, output, ipv6);
		if(result == 0) {
			ipAddr.setValue((String) output.getObject()[0]);
		}
		return result;
	}

	/** Gets the local (host) IP address.
	 */
	public int getLocalIP(ReturnValue<String> ipAddr) {
		return getLocalIP(ipAddr, false);
	}

	/** Enables IPv6 for a specified |channel|.
	 */
	public int enableIPv6(int channel) {
		return EnableIPv6(_p, channel);
	}

	/** Gets the current IPv6 staus for a specified |channel|.
	 */
	public boolean ipv6IsEnabled(int channel) {
		return IPv6IsEnabled(_p, channel);
	}

	/** Enables a port and IP address filter for incoming packets on a<br/>
	 *  specific |channel|.
	 */
	public int setSourceFilter(int channel,
			int rtpPort, int rtcpPort, String ipAddr) {
		return SetSourceFilter(_p, channel, rtpPort, rtcpPort, ipAddr);
	}

	/** Enables a port and IP address filter for incoming packets on a<br/>
	 *  specific |channel|.
	 */
	public int setSourceFilter(int channel, int rtpPort, int rtcpPort) {
		return setSourceFilter(channel, rtpPort, rtcpPort, null);
	}

	/** Enables a port and IP address filter for incoming packets on a<br/>
	 *  specific |channel|.
	 */
	public int setSourceFilter(int channel, int rtpPort) {
		return setSourceFilter(channel, rtpPort, 0, null);
	}

	/** Gets the current port and IP-address filter for a specified |channel|.
	 */
	public int getSourceFilter(int channel, ReturnValue<Integer> rtpPort, 
			ReturnValue<Integer> rtcpPort, ReturnValue<String> ipAddr) {
		OutputParam output = new OutputParam();
		int result = GetSourceFilter(_p, channel, output);
		if(result == 0) {
			rtpPort.setValue((Integer) output.getObject()[0]);
			rtcpPort.setValue((Integer) output.getObject()[1]);
			ipAddr.setValue((String) output.getObject()[2]);
		}
		return result;
	}

	/** Sets the six-bit Differentiated Services Code Point (DSCP) in the<br/>
	 *  IP header of the outgoing stream for a specific |channel|.
	 */
	public int setSendTOS(int channel, int DSCP, int priority, boolean useSetSockopt) {
		return SetSendTOS(_p, channel, DSCP, priority, useSetSockopt);
	}

	/** Sets the six-bit Differentiated Services Code Point (DSCP) in the<br/>
	 *  IP header of the outgoing stream for a specific |channel|.
	 */
	public int setSendTOS(int channel, int DSCP, int priority) {
		return setSendTOS(channel, DSCP, priority, false);
	}

	/** Sets the six-bit Differentiated Services Code Point (DSCP) in the<br/>
	 *  IP header of the outgoing stream for a specific |channel|.
	 */
	public int setSendTOS(int channel, int DSCP) {
		return setSendTOS(channel, DSCP, -1, false);
	}

	/** Gets the six-bit DSCP in the IP header of the outgoing stream for<br/>
	 *  a specific channel.
	 */
	public int getSendTOS(int channel, ReturnValue<Integer> DSCP, 
			ReturnValue<Integer> priority, ReturnValue<Boolean> useSetSockopt) {
		OutputParam output = new OutputParam();
		int result = GetSendTOS(_p, channel, output);
		if(result == 0) {
			DSCP.setValue((Integer) output.getObject()[0]);
			priority.setValue((Integer) output.getObject()[1]);
			useSetSockopt.setValue((Boolean) output.getObject()[2]);
		}
		return result;
	}

	/** Sets the Generic Quality of Service (GQoS) service level.<br/>
	 *  The Windows operating system then maps to a Differentiated Services<br/>
	 *  Code Point (DSCP) and to an 802.1p setting. [Windows only]
	 */
	public int setSendGQoS(int channel, boolean enable, int serviceType, 
			int overrideDSCP) {
		return SetSendGQoS(_p, channel, enable, serviceType, overrideDSCP);
	}

	/** Sets the Generic Quality of Service (GQoS) service level.<br/>
	 *  The Windows operating system then maps to a Differentiated Services<br/>
	 *  Code Point (DSCP) and to an 802.1p setting. [Windows only]
	 */
	public int setSendGQoS(int channel, boolean enable, int serviceType) {
		return setSendGQoS(channel, enable, serviceType, 0);
	}

	/** Gets the Generic Quality of Service (GQoS) service level.
	 */
	public int getSendGQoS(int channel, ReturnValue<Boolean> enabled, 
			ReturnValue<Integer> serviceType,
			ReturnValue<Integer> overrideDSCP) {
		OutputParam output = new OutputParam();
		int result = GetSendGQoS(_p, channel, output);
		if(result == 0) {
			enabled.setValue((Boolean) output.getObject()[0]);
			serviceType.setValue((Integer) output.getObject()[1]);
			overrideDSCP.setValue((Integer) output.getObject()[2]);
		}
		return result;
	}

	/** Enables or disables warnings that report if packets have not been<br/>
	 *  received in |timeoutSeconds| seconds for a specific |channel|.
	 */
	public int setPacketTimeoutNotification(int channel, boolean enable, int timeoutSeconds) {
		return SetPacketTimeoutNotification(_p, channel, enable, timeoutSeconds);
	}

	/** Enables or disables warnings that report if packets have not been<br/>
	 *  received in |timeoutSeconds| seconds for a specific |channel|.
	 */
	public int setPacketTimeoutNotification(int channel, boolean enable) {
		return setPacketTimeoutNotification(channel, enable, 2);
	}

	/** Gets the current time-out notification status.
	 */
	public int getPacketTimeoutNotification(int channel, 
			ReturnValue<Boolean> enabled, 
			ReturnValue<Integer> timeoutSeconds) {
		OutputParam output = new OutputParam();
		int result = GetPacketTimeoutNotification(_p, channel, output);
		if(result == 0) {
			enabled.setValue((Boolean) output.getObject()[0]);
			timeoutSeconds.setValue((Integer) output.getObject()[1]);
		}
		return result;
	}

	/** Installs the observer class implementation for a specified |channel|.
	 */
	public int registerDeadOrAliveObserver(int channel, VoEConnectionObserver observer) {
		Utility.throwNullPointerException(observer, "observer");
		return RegisterDeadOrAliveObserver(_p, channel, observer);
	}

	/** Removes the observer class implementation for a specified |channel|.
	 */
	public int deRegisterDeadOrAliveObserver(int channel) {
		return DeRegisterDeadOrAliveObserver(_p, channel);
	}

	/** Enables or disables the periodic dead-or-alive callback functionality<br/>
	 *  for a specified |channel|.
	 */
	public int setPeriodicDeadOrAliveStatus(int channel, boolean enable, int sampleTimeSeconds) {
		return SetPeriodicDeadOrAliveStatus(_p, channel, enable, sampleTimeSeconds);
	}

	/** Enables or disables the periodic dead-or-alive callback functionality<br/>
	 *  for a specified |channel|.
	 */
	public int setPeriodicDeadOrAliveStatus(int channel, boolean enable) {
		return setPeriodicDeadOrAliveStatus(channel, enable, 2);
	}

	/** Gets the current dead-or-alive notification status.
	 */
	public int getPeriodicDeadOrAliveStatus(int channel, 
			ReturnValue<Boolean> enabled, 
			ReturnValue<Integer> sampleTimeSeconds) {
		OutputParam output = new OutputParam();
		int result = GetPeriodicDeadOrAliveStatus(_p, channel, output);
		if(result == 0) {
			enabled.setValue((Boolean) output.getObject()[0]);
			sampleTimeSeconds.setValue((Integer) output.getObject()[1]);
		}
		return result;
	}

	/** Handles sending a raw UDP data packet over an existing RTP or RTCP<br/>
	 *  socket.
	 */
	public int sendUDPPacket(int channel,
			byte[] buffer, ReturnValue<Integer> transmittedBytes, boolean useRtcpSocket) {
		OutputParam output = new OutputParam();
		int result = SendUDPPacket(_p, channel, buffer, output, useRtcpSocket);
		if(result == 0) {
			transmittedBytes.setValue((Integer) output.getObject()[0]);
		}
		return result;
	}

	/** Handles sending a raw UDP data packet over an existing RTP or RTCP<br/>
	 *  socket.
	 */
	public int sendUDPPacket(int channel, byte[] buffer, ReturnValue<Integer> transmittedBytes) {
		return sendUDPPacket(channel, buffer, transmittedBytes, false);
	}

	protected VoENetwork(long p) {
		_p = p;
	}

	protected long _p;

	// [end]
	
	
	
	
	
	
	// [start] jni api

	// Factory for the VoENetwork sub-API. Increases an internal
	// reference counter if successful. Returns NULL if the API is not
	// supported or if construction fails.
	private static native long GetInterface(long p_voiceEngine);

	// Releases the VoENetwork sub-API and decreases an internal
	// reference counter. Returns the new reference count. This value should
	// be zero for all sub-API:s before the VoiceEngine object can be safely
	// deleted.
	private static native int Release(long p_VoENetwork);

	// Installs and enables a user-defined external transport protocol for a
	// specified |channel|.
	private static native int RegisterExternalTransport(long p_VoENetwork,
			int channel, Transport transport);

	// Removes and disables a user-defined external transport protocol for a
	// specified |channel|.
	private static native int DeRegisterExternalTransport(long p_VoENetwork,
			int channel);

	// The packets received from the network should be passed to this
	// function when external transport is enabled. Note that the data
	// including the RTP-header must also be given to the VoiceEngine.
	private static native int ReceivedRTPPacket(long p_VoENetwork, int channel,
			byte[] buffer);

	// The packets received from the network should be passed to this
	// function when external transport is enabled. Note that the data
	// including the RTCP-header must also be given to the VoiceEngine.
	private static native int ReceivedRTCPPacket(long p_VoENetwork,
			int channel, byte[] buffer);

	// Gets the source ports and IP address of incoming packets on a
	// specific |channel|.
	private static native int GetSourceInfo(long p_VoENetwork, int channel,
			OutputParam param);

	// Gets the local (host) IP address.
	private static native int GetLocalIP(long p_VoENetwork, OutputParam param,
			boolean ipv6);

	// Enables IPv6 for a specified |channel|.
	private static native int EnableIPv6(long p_VoENetwork, int channel);

	// Gets the current IPv6 staus for a specified |channel|.
	private static native boolean IPv6IsEnabled(long p_VoENetwork, int channel);

	// Enables a port and IP address filter for incoming packets on a
	// specific |channel|.
	private static native int SetSourceFilter(long p_VoENetwork, int channel,
			int rtpPort, int rtcpPort, String ipAddr);

	// Gets the current port and IP-address filter for a specified |channel|.
	private static native int GetSourceFilter(long p_VoENetwork, int channel,
			OutputParam param);

	// Sets the six-bit Differentiated Services Code Point (DSCP) in the
	// IP header of the outgoing stream for a specific |channel|.
	private static native int SetSendTOS(long p_VoENetwork, int channel,
			int DSCP, int priority, boolean useSetSockopt);

	// Gets the six-bit DSCP in the IP header of the outgoing stream for
	// a specific channel.
	private static native int GetSendTOS(long p_VoENetwork, int channel,
			OutputParam param);

	// Sets the Generic Quality of Service (GQoS) service level.
	// The Windows operating system then maps to a Differentiated Services
	// Code Point (DSCP) and to an 802.1p setting. [Windows only]
	private static native int SetSendGQoS(long p_VoENetwork, int channel,
			boolean enable, int serviceType, int overrideDSCP);

	// Gets the Generic Quality of Service (GQoS) service level.
	private static native int GetSendGQoS(long p_VoENetwork, int channel,
			OutputParam param);

	// Enables or disables warnings that report if packets have not been
	// received in |timeoutSeconds| seconds for a specific |channel|.
	private static native int SetPacketTimeoutNotification(long p_VoENetwork,
			int channel, boolean enable, int timeoutSeconds);

	// Gets the current time-out notification status.
	private static native int GetPacketTimeoutNotification(long p_VoENetwork,
			int channel, OutputParam param);

	// Installs the observer class implementation for a specified |channel|.
	private static native int RegisterDeadOrAliveObserver(long p_VoENetwork,
			int channel, VoEConnectionObserver observer);

	// Removes the observer class implementation for a specified |channel|.
	private static native int DeRegisterDeadOrAliveObserver(long p_VoENetwork,
			int channel);

	// Enables or disables the periodic dead-or-alive callback functionality
	// for a specified |channel|.
	private static native int SetPeriodicDeadOrAliveStatus(long p_VoENetwork,
			int channel, boolean enable, int sampleTimeSeconds);

	// Gets the current dead-or-alive notification status.
	private static native int GetPeriodicDeadOrAliveStatus(long p_VoENetwork,
			int channel, OutputParam param);

	// Handles sending a raw UDP data packet over an existing RTP or RTCP
	// socket.
	private static native int SendUDPPacket(long p_VoENetwork, int channel,
			byte[] buffer, OutputParam transmittedBytes, boolean useRtcpSocket);

	// [end]
}
